#include "app_pool.h"
#include <pthread.h>
#include <mqueue.h>
#include <stdio.h>
#include <unistd.h>

static pthread_t threads[MAX_THREAD_NUM];

static mqd_t mq;
/**
 * @brief 定义线程池的工作内容
 * 定义线程要执行什么工作 
         每个线程启动一个死循环 不停的尝试从队列中取得任务
         解任务包
          每个任务包含a  执行函数  b 执行参数
          每个线程要取出函数 用函数执行参数 
 */
static void *app_pool_thread_func(void *arg)
{
    while (1)
    {   
        task_t task;
        // 从队列中取任务
        ssize_t task_size=  mq_receive(mq, (char *)&task , sizeof(task) , 0);
        if(task_size>0)
        {
            if(task.task_func)
            {   // 执行任务
                task.task_func(task.task_arg);
            }
        }
         
    }
    return NULL;
}


/**
 * @brief  初始化线程池
 * @return 0 成功  -1 失败
 * 
 *  1 创建线程数组 并且开辟出来
 *  2  创建队列  
 */
int app_pool_init()
{
    //1 创建线程数组 并且开辟出来
    for (int i = 0; i < MAX_THREAD_NUM; i++)
    {
        pthread_create(&threads[i], NULL, app_pool_thread_func, NULL);
        printf("创建线程%d\n", i);
    }

    //2  创建队列  
    mq_unlink(POOL_QUEUE_NAME); //清空历史残留队列

    struct mq_attr attr;
    attr.mq_maxmsg = 100;
    attr.mq_msgsize =  sizeof(task_t);

    mq=mq_open(POOL_QUEUE_NAME, O_CREAT | O_RDWR, 0666, &attr);
    if(mq == -1)
    {
        perror("mq_open error");
        return -1;
    }

    return 0;
}



/**
 * @brief 提供一个对外函数 用来向线程池提交任务  
 * 
 * @param func 
 * @param arg 

 */
 int  app_pool_submit_task(void *(*func)(void *),void *arg)
 {
    //1 要把函数 和参数 组合成任务结构体 
    task_t task;
    task.task_func=func;
    task.task_arg=arg;
    //2 把任务发送到队列中
    int ret= mq_send(mq,(char *)&task,sizeof(task),0);
    if(ret==-1)
    {
        perror("mq_send error");
        return -1;
    }
    return 0;
 }  
 

/**
 * @brief 线程池销毁
 * 
 */
 void app_pool_destroy()
 {
     //1 销毁线程池
     for (size_t i = 0; i < MAX_THREAD_NUM; i++)
     {
         pthread_cancel(threads[i]);
     }
     
     //2 销毁队列
     mq_close(mq);
     mq_unlink(POOL_QUEUE_NAME);
 }